/*
 * ExplicaEntityView.java
 *
 * $Id: ExplicaEntityView.java,v 1.19 2009-10-27 10:09:06 mario Exp $
 */
package org.ceteca.explica.client.gui;

import java.io.PrintWriter;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.ceteca.explica.client.ClientContext;
import org.ceteca.explica.client.gui.common.CommonClient;
import org.ceteca.explica.core.ExplicaException;
import org.ceteca.explica.core.InterfaceErrors;
import org.ceteca.explica.core.InterfaceExplica;
import org.ceteca.explica.core.common.RegistryOT;
import org.ceteca.explica.core.installer.EntityLauncher;
import org.ceteca.explica.core.installer.EntityOT;
import org.ceteca.explica.core.installer.FieldOT;
import org.ceteca.explica.core.util.OperationResult;
import org.ceteca.javaglade.Gui;
import org.ceteca.javaglade.InterfaceGladeGtk;
import org.ceteca.javaglade.InterfaceGladeParser;
import org.ceteca.javaglade.JavaGladeException;
import org.ceteca.javaglade.handlers.GenericHandler;
import org.ceteca.javaglade.toolkit.swt.SwtWidget;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

import java.util.Vector;

/**
 * Helper class that implements the Explica entity GUI. 
 * It completes the glade file specification to add extra features.
 * It also implements the event handlers for the Explica entity buttons.
 * <br/>
 * Responsibilities:
 * <ul>
 * 	<li>Definition and inicialization of the Explica entity GUI. </li>
 *  <li>Event management for the Explica entity widgets.</li>
 * </ul>
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2008 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class ExplicaEntityView extends GenericHandler {
	/** Parent GUI where the entity panel will be embedded */
	protected Gui parentGui;
	/** Parent widget where the entity panel will be embedded */
	protected SwtWidget parentWidget;
	/** Root panel where the entity view contents will be placed */
	protected SwtWidget viewPanel;
	/** Name of the entity GUI */
	protected String entityGuiName;
	/** Data of the entity */
	protected EntityOT entityData;
	/** Instance of the logging system for the module */
	protected Logger logger;
	/** Instance of the entity launcher handler object */
	protected EntityLauncher entityLauncher;
	/** List of fields that will be showed in the searching combobox */
	protected ArrayList<FieldOT> comboSearchItems;
	/** Parent panel where the entity view will be embedded. It may be the main window entity panel, a selection window panel
	 * or a panel inside the master entity edition window. */
	protected Composite parentPanel;
	
	private Vector<ExplicaEventListener> listeners=new Vector<ExplicaEventListener>();
	
	/** 
	 * Default constructor of the EntityView class.
	 * @param name String, name of the interface object.
	 */
	public ExplicaEntityView(String name) {
		this.entityGuiName = name;
		this.parentGui = null;
//		this.logger = null;
		this.logger = ClientContext.getInstance().getLogger(InterfaceGladeParser.JAVAGLADE_LOG_CATEGORY);
		this.entityData = null;
		this.entityLauncher = null;
		this.parentPanel = null;
		this.comboSearchItems = new ArrayList<FieldOT>();
		this.viewPanel = null;
	}
	
	/**
	 * Initializes the Explica Entity Viewer engine and builds
	 * the entity panel. Searches automatically for the glade interface 
	 * file with the module GUI configuration.
	 */
	public void buildEntityView() {
		// Build the parent composite that will hold the entity view
		Composite c = (Composite)ExplicaGUIBuilder.getInstance().getToolkit().
			emptyPanel(ClientContext.getInstance().getFakeParent(), InterfaceExplica.EXPLICA_ENTITY_PANEL_NAME);
		c.setLayout(new FillLayout());
//		c.setBackground(ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_YELLOW));
		this.viewPanel = new SwtWidget(InterfaceExplica.EXPLICA_ENTITY_PANEL_NAME, c); 
//		((Composite)this.viewPanel.getWidget()).setBackground(ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_GREEN));
		
		// Build the entity panel and embed it into the correspondent module panel.
		try {
			this.gui = ExplicaGUIBuilder.getInstance().buildGUI(this.entityGuiName,
					InterfaceExplica.EXPLICA_ENTITY_GLADE_PATH,
					ExplicaGUIBuilder.getInstance().getGui(InterfaceExplica.EXPLICA_CORE_GLADE_NAME),
					InterfaceExplica.EXPLICA_ENTITY_CONTENTS_PANEL_NAME,
					this.viewPanel.getWidget(),
					"fakeParent",
					ClientContext.getInstance().getResourceDir());
			
			Button button1 = (Button)this.gui.getWidget("toolbuttonExplicaEntitySearch");
			GridData data = (GridData)button1.getParent().getLayoutData();
			if (data == null)
				data = new GridData();
			
			data.verticalAlignment = SWT.FILL;
			button1.getParent().setLayoutData(data);
			
			// Get the contents panel
			Composite contentsPanel = (Composite)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_CONTENTS_PANEL_NAME);
//			contentsPanel.setBackground(ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_BLACK));
			
			// Add a handler for the entity hiding event
			ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_HIDE, contentsPanel, "on_entity_hidden", this);
			ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_FOCUSOUT, contentsPanel, "on_entity_hidden", this);
			ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_DESTROY, contentsPanel, "on_entity_hidden", this);
			
			// Get the scroll panel
//			Composite scrollPanel = (Composite)this.gui.getWidget("scrollExplicaMainEntity");
//			scrollPanel.setBackground(ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_BLUE));
		}
		catch (JavaGladeException jEx) {
			jEx.printStackTrace();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		ExplicaGUIBuilder.getInstance().printGUIs(new PrintWriter(System.out));
		
		// Connect the entity tree selection listener
		this.connectEntityTreeSelectionListener();
		
		// Connect the entity toolbar buttons to their handlers.
		this.connectToolbarButtons();
	}
	
	/**
	 * Shows an entity in the entity view. Fills the entity view with the data
	 * of the selected entity. 
	 * @param parentGui Gui, parent GUI where the view will be embedded.
	 * @param entLauncher EntityLauncher, instance of the entity launcher that will be
	 * shown in the entity view.
	 * @param logger Logger, instance of the logger for the entity view.
	 * @param parentWidget SwtWidget, parent widget where the contents of the view
	 * will be embedded.
	 */
	public void showEntityView(Gui parentGui, EntityLauncher entLauncher, Logger logger, SwtWidget parentWidget) {
		this.logger = logger;
		
		System.out.println("Showing entity view: " + entLauncher + " - " + parentWidget);
		// Clear the view to remove the previous contents
		this.clearView();

		this.unlinkGui();
		this.linkGui(parentGui, parentWidget);

		this.entityLauncher = entLauncher;
		this.entityData = entLauncher.getEntity();
		this.parentWidget = parentWidget;
		this.parentPanel = (parentWidget!=null)?(Composite)parentWidget.getWidget():null;
		this.parentGui = parentGui;
		
		this.logger.info("Showing entity contents");
		
		// Fill the search in combo with the searchable fields for the entity
		// and the entity table with the fields of the columns' headers.
		this.fillEntityFields();
		
		// Fill the tree viewer with the existing registries of the entity.
		this.fillEntityTable();
		
		// Distribute the columns
//		Rectangle rect = this.parentPanel.getParent().getClientArea();
//		this.distributeColumns(rect.width - 40);
		
		// Adjust the entity view panel to fit with the parent's layout
		if (this.parentPanel.getLayout() instanceof StackLayout) {
			((StackLayout)this.parentPanel.getLayout()).topControl = (Control)this.viewPanel.getWidget();
		}
		else if (this.parentPanel.getLayout() instanceof GridLayout) {
			GridData gridData = new GridData();
			gridData.horizontalAlignment = SWT.FILL;
			gridData.grabExcessHorizontalSpace = true;
			gridData.verticalAlignment = SWT.FILL;
			gridData.grabExcessVerticalSpace = true;
			((Control)this.viewPanel.getWidget()).setLayoutData(gridData);
		}
		else if (this.parentPanel.getLayout() instanceof RowLayout) {
			((RowLayout)this.parentPanel.getLayout()).fill = true;
		}
		
		System.out.println("VIEW PANEL: " + this.viewPanel.getWidgetName() + " --> " + this.viewPanel.getWidget() + " [" + ((Control)this.viewPanel.getWidget()).getParent() + "]");
		System.out.println("VIEW PANEL LAYOUT: " + ((Composite)this.viewPanel.getWidget()).getLayout());		
		System.out.println("VIEW PANEL LAYOUT DATA: " + ((Control)this.viewPanel.getWidget()).getLayoutData());
		
		
		Tree tree = this.getEntityTreeWidget();
		System.out.println("TREE LAYOUT DATA: " + tree.getLayoutData());
		System.out.println("TREE PARENT LAYOUT: " + tree.getParent().getLayout());
		
		SwtWidget tWid = this.gui.getSwtWidget(InterfaceExplica.EXPLICA_ENTITY_TREE_NAME);
		System.out.println("TREE PARENT: " + tWid.getParent().getWidgetName() + " [" + ((Composite)tWid.getParent().getWidget()).getLayout() + "]");
		
		this.parentPanel.layout();

		ExplicaGUIBuilder.getInstance().printGUIs(this.logger);
		for (TreeColumn column: tree.getColumns()) {
			System.out.println(column.getWidth());
			this.logger.debug("$$$ Column width: " + column.getWidth());
		}
	}
	
	/**
	 * Fills the entity view with the selected data. 
	 */
	public void showEntityView() {
		this.logger.info("Showing entity contents");

		// Fill the tree viewer with the existing registries of the entity.
		this.fillEntityTable();
		
		// Distribute the columns
//		this.distributeColumns(parentPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT).x - 10);
		
		this.parentPanel.layout(true);
		
		Tree entityTree = this.getEntityTreeWidget();
		for (TreeColumn column: entityTree.getColumns()) {
			System.out.println(column.getWidth());
			this.logger.debug("$$$ Column width: " + column.getWidth());
		}
	}
	
	/**
	 * Connects the entity tree to their correspondent selection event
	 * handler.
	 */
	protected void connectEntityTreeSelectionListener() {
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();
		// Connect the select signal to the table
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_SELECTCURSORROW, entityTree, 
				InterfaceExplica.EXPLICA_ENTITY_SELECTED_HANDLER, this);
		
		// Connect the double click signal to the table
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_DOUBLECLICKED, entityTree, 
				InterfaceExplica.EXPLICA_ENTITY_DOUBLECLICKED_HANDLER, this);
	}

	/**
	 * Connects the toolbar buttons to their correspondent event
	 * handlers.
	 */
	protected void connectToolbarButtons() {
		// Get the toolitem for adding a new entity
		ToolItem toolItemAdd = (ToolItem)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_TOOLITEM_ADD_NAME);
		// Connect the signal to the button
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED, toolItemAdd, 
				InterfaceExplica.EXPLICA_ENTITY_ADD_BUTTON_CLICKED_HANDLER, this);
		System.out.println("TOOLITEM ADD: " + toolItemAdd);
		
		// Get the toolitem for deleting a entity
		ToolItem toolItemDel = (ToolItem)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_TOOLITEM_DEL_NAME);
		// Connect the signal to the button
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED, toolItemDel, 
				InterfaceExplica.EXPLICA_ENTITY_DEL_BUTTON_CLICKED_HANDLER, this);
		System.out.println("TOOLITEM DEL: " + toolItemDel);
		
		// Get the toolitem for editing a entity
		ToolItem toolItemEdit = (ToolItem)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_TOOLITEM_EDIT_NAME);
		// Connect the signal to the button
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED, toolItemEdit, 
				InterfaceExplica.EXPLICA_ENTITY_EDIT_BUTTON_CLICKED_HANDLER, this);
		System.out.println("TOOLITEM EDIT: " + toolItemEdit);
		
		// Get the toolitem for printing a entity
		ToolItem toolItemPrint = (ToolItem)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_TOOLITEM_PRINT_NAME);
		// Connect the signal to the button
		ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED, toolItemPrint, 
				InterfaceExplica.EXPLICA_ENTITY_PRINT_BUTTON_CLICKED_HANDLER, this);
		System.out.println("TOOLITEM PRINT: " + toolItemPrint);
		
		// Get the toolitem for searching (going to) a entity
		Button buttonGoTo = (Button)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_TOOLITEM_GOTO_NAME);
		if (buttonGoTo != null) {
			// Connect the signal to the button
			ExplicaGUIBuilder.getInstance().connectSignal(InterfaceGladeGtk.GTK_SIGNAL_TYPE_CLICKED, buttonGoTo, 
					InterfaceExplica.EXPLICA_ENTITY_GOTO_BUTTON_CLICKED_HANDLER, this);
		}
		System.out.println("TOOLITEM GOTO: " + buttonGoTo);
	}
	
	/**
	 * Fills the search in combo with the searchable fields defined
	 * for the entity.
	 */
	protected void fillEntityFields() {
		// Get the entity search in combo widget
		Combo comboSearch = (Combo)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_SEARCH_COMBO_NAME);
		
		this.logger.debug("Entity combo of search in found: " + comboSearch + " - " + comboSearch.getParent().getLayout());
		
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();
		entityTree.setHeaderVisible(true);

		// Adjust the entity tree to fit with the parent panel's layout
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.verticalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		entityTree.setLayoutData(gridData);
		
		this.logger.debug("Entity tree found: " + entityTree);
		
		// Add the identifier field as the first column. This column will be invisible.
		if (this.entityData != null) {
			this.logger.debug("Adding identifier field: " + this.entityData.getIdField());
			TreeColumn column = new TreeColumn(entityTree, SWT.LEFT);
			column.setText(this.entityData.getIdField());
			column.setWidth(0);
			column.setResizable(false);
			column.setMoveable(false);
		}
		
		// Add the fields to the search in combo and the entity table fields column headers.
		if (this.entityData != null && this.entityData.getLFields() != null && this.entityData.getLFields().size() > 0) {
			// The column width will be automatically adjusted. The same width will be
			// assigned to each column up to the tree total width.
//			int columnWidth = (entityTree.getParent().getParent().getParent().getClientArea().width - 15) / this.entityData.getLFields().size();
			int columnWidth = (parentPanel.getParent().getClientArea().width - 15) / this.getVisibleFieldsCount();

			this.logger.debug("Adding fields: " + this.entityData.getLFields().size() + " (" + columnWidth + " px)");
			
			for (FieldOT field : this.entityData.getLFields()) {
				this.logger.debug("Adding field: " + field.getName() + " - " + field.isSearchable() + " [" + field.isVisible() + "]");
				
				// If the field is searchable then add it to the entity search combo
				if (field.isSearchable()) {
					comboSearch.add(field.getName());
					this.comboSearchItems.add(field);
				}
		
				// Add the field to the entity table column headers.
				if (field.isVisible()) {
					TreeColumn column = new TreeColumn(entityTree, SWT.LEFT);
					column.setText(field.getName());
					column.setWidth(columnWidth);
				}
			} // for each entity field
		} // if exists any entity field
		
		this.logger.info("Entity tree created: " + entityTree.getColumnCount() + " columns     " + entityTree.getColumns());
		this.logger.info("Entity tree created: " + entityTree.getItemCount() + " items     " + entityTree.getItems());
		
		for (TreeColumn column : entityTree.getColumns()) {
			System.out.println(column.getWidth());
		}
	}
	
	/**
	 * Fills the entity tree viewer with the entity data.
	 */
	public void fillEntityTable() {
		if (this.entityLauncher != null) {
			ArrayList<RegistryOT> lRegistries = null;
			// If the entity is a detail of a master entity --> Show the multiselection entity view panel
			lRegistries = this.entityLauncher.queryEntityWithFormat(null, null);
			
			this.logger.debug("FILLING THE ENTITY VIEW'S TABLE: " + lRegistries.size());
			for (RegistryOT reg: lRegistries) {
				this.logger.debug(reg.getId() + " ... " + reg.toString());
			}
			this.fillEntityTable(lRegistries);
		}
	}
	
	/**
	 * Fills the entity tree viewer with the entity data.
	 */
	public void fillEntityTable(ArrayList lRegistries) {
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();
		this.logger.debug("Filling the entity view table: " + entityTree);
		
		// Clear the entity table registries
		entityTree.clearAll(true);
		entityTree.removeAll();
		
		// Build the items for the available entity registries
		for (int i=0; lRegistries!=null && i<lRegistries.size(); i++) {
			RegistryOT registry = (RegistryOT)lRegistries.get(i);
			String[] lValues = new String[registry.getColumnCount()];
			for (int j=0; j<registry.getColumnCount(); j++) {
				String value = registry.getValue(j); 
				lValues[j] = value;
			}
				
			this.logger.debug("Setting new item values: (" + registry.getId() + ") " + lValues.length + " --> " + lValues.toString());
				
			// Add registry to the entity table
			TreeItem treeItem = (TreeItem)ExplicaGUIBuilder.getInstance().getToolkit().treeItem(entityTree, InterfaceExplica.EXPLICA_ENTITY_TREEITEM_NAME + "_" + registry.getId(), lValues, null, i);
				
			// Add the widget to the catalog
			this.gui.addWidget(InterfaceExplica.EXPLICA_ENTITY_TREEITEM_NAME + "_" + registry.getId(), treeItem, InterfaceExplica.EXPLICA_ENTITY_TREE_NAME);
		}

		this.logger.info("Entity tree created: " + entityTree.getColumnCount() + " columns     " + entityTree.getColumns());
		this.logger.info("Entity tree created: " + entityTree.getItemCount() + " items     " + entityTree.getItems());
	}
	
	/**
	 * Sets the default column with of the entity table.
	 * @param width int, width in pixels.
	 */
	public void setColumnWidth(int width) {
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();
		
		// If the entity tree is not null and is not empty (more than the first hidden id column)
		if (entityTree != null && entityTree.getColumnCount() > 1) {
			// Ignore the first column that is the hidden column with the internal id of the registry.
			for (int i=1; i<entityTree.getColumnCount(); i++) {
				entityTree.getColumn(i).setWidth(width);
			} // for each column
		} // if entityTree not empty
	}
	
	/**
	 * Calculates the width of the columns distributing them equally
	 * to fit the provided container total width.
	 * @param totalWidth int, container total width in pixels.
	 */
	public void distributeColumns(int totalWidth) {
		System.out.println("Distributing columns: " + totalWidth);
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();

		// If the entity tree is not null and is not empty (more than the first hidden id column)
		if (entityTree != null && entityTree.getColumnCount() > 1) {
			// Calculate the fitting width for each column
			int width = totalWidth / this.getVisibleFieldsCount();
			
			// Ignore the first column that is the hidden column with the internal id of the registry.
			for (int i=1; i<entityTree.getColumnCount(); i++) {
				entityTree.getColumn(i).setWidth(width);
			} // for each column
		} // if entityTree not empty
	}
	
	/**
	 * Handler for the entity add button click event.
	 * Calls the correspondent entity launcher method for adding a new entity.
	 * @param e Event, entity add button clicked event data.
	 */
	public void on_entityAddButton_clicked(Event e) {
		if (this.entityLauncher != null) {
			this.entityLauncher.addEntity();
		}
	}
	
	/**
	 * Handler for the entity delete button click event.
	 * Calls the correspondent entity launcher method for deleting an entity.
	 * @param e Event, entity delete button clicked event data.
	 */
	public void on_entityDelButton_clicked(Event e) {
		if (this.entityLauncher != null) {
			// Get the entity table widget
			Tree entityTree = this.getEntityTreeWidget();
			this.logger.debug("Entity tree found: " + entityTree);
			
			// Get the selected table item (selected entity)
			try {
				ArrayList<Long> lSelRegistries = new ArrayList<Long>();
				TreeItem[] selItems = null;
				selItems = entityTree.getSelection();
				for (int i=0; selItems != null && i < selItems.length; i++) {
					Long idRegistry = new Long(selItems[i].getText(0));
					lSelRegistries.add(idRegistry);
				} // for each selected item
				
				this.logger.debug("Selected entity registries: " + lSelRegistries.size());
				
				OperationResult result = this.entityLauncher.delEntity(lSelRegistries);
				if (result != null && result.getResult() == OperationResult.RESULT_OK) {
/*					// Remove the deleted tree items from the tree
					for (int i=0; selItems != null && i < selItems.length; i++) {
						this.logger.debug(String.format("Removing (%s) selected registry: %s",
								this.entityData.getName(),
								selItems[i].getText()));
						selItems[i].dispose();
					} // for each selected item
*/
					this.logger.info("Entity registry successfully deleted!" + lSelRegistries.get(0));
				}
				else {
					((CommonClient)this.entityLauncher).showErrorMessages(result);
				}
			} // try
			catch (Exception ex) {
				this.logger.error("Error deleting entity registry!", ex);
			} // catch exception
			
			// Get the parent widget that will hold the entity panel
			this.parentPanel.layout(true);
		}
	}
	
	/**
	 * Handler for the entity edit button click event.
	 * Calls the correspondent entity launcher method for editing an entity.
	 * @param e Event, entity edit button clicked event data.
	 */
	public void on_entityEditButton_clicked(Event e) {
		this.logger.debug("Edit button clicked: " + this.entityGuiName);
		
		if (this.entityLauncher != null) {
			this.entityLauncher.editEntity();
		}
	}
	
	/**
	 * Handler for the entity print button click event.
	 * Calls the correspondent entity launcher method for printing an entity.
	 * @param e Event, entity print button clicked event data.
	 */
	public void on_entityPrintButton_clicked(Event e) {
		this.logger.debug("Print button clicked: " + this.entityGuiName);
		
		if (this.entityLauncher != null) {
			this.entityLauncher.printEntity();
		}
	}
	
	/**
	 * Handler for the entity search button click event.
	 * Calls the correspondent entity launcher method for searching for 
	 * (going to) an entity.
	 * @param e Event, entity search button clicked event data.
	 */
	public void on_entityGotoButton_clicked(Event e) {
		if (this.entityLauncher != null) {
			// Get the searched field combo item
			Combo searchInCombo = (Combo)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_SEARCH_COMBO_NAME);
			this.logger.debug("Entity search in combo found: " + searchInCombo);
			
			FieldOT selField = null;
			try {
				selField = this.comboSearchItems.get(searchInCombo.getSelectionIndex());
			}
			catch (Exception ex) {
				this.logger.error("Error getting the selected search in field from the combo!", ex);
				selField = null;
			}
			String id = selField!=null?selField.getId():null;
			// Get the searched text item
			Text searchText = (Text)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_SEARCH_TEXT_NAME);
			String val = searchText!=null?searchText.getText():null;
			
			this.logger.info("Searching entity with values: " + id + " = " + val);
			ArrayList lRegistries = this.entityLauncher.queryEntityWithFormat(id, val);
			
			this.fillEntityTable(lRegistries);
			
			// Get the parent widget that will hold the entity panel
			this.parentPanel.layout(true);
		}
	}
	
	public void on_entity_selected(Event e) {
		this.logger.info("Selecting a new item from the entity tree...");
		// Get the entity table widget
		Tree entityTree = this.getEntityTreeWidget();
		
		// Get the selected table item (selected entity)
		try {
			Long selectedItem = null;
			TreeItem[] selItems = entityTree.getSelection();
			if (selItems != null && selItems.length > 0) {
				selectedItem = new Long(selItems[0].getText(0));
			} // for each selected item
			
			
			this.logger.info("Entity selected: " + selectedItem);
			this.entityLauncher.selectEntity(selectedItem);
		} // try
		catch (Exception ex) {
			ex.printStackTrace();
		} // catch exception
	}
	
	public void on_entity_doubleclicked(Event e) {
		System.out.println("¡¡¡¡¡¡ DOUBLE CLICK !!!!!!");
		this.logger.info("Editing an item from the entity tree...");
		if (this.entityLauncher != null) {
			this.entityLauncher.editEntity();
		}
	}
	
	public SwtWidget getEntityTree() {
		this.logger.debug("Getting entity tree: " + InterfaceExplica.EXPLICA_ENTITY_TREE_NAME + " --> " + this.gui.getSwtWidget(InterfaceExplica.EXPLICA_ENTITY_TREE_NAME));
		return this.gui.getSwtWidget(InterfaceExplica.EXPLICA_ENTITY_TREE_NAME);
	}
	
	public Tree getEntityTreeWidget() {
		return (Tree)this.getEntityTree().getWidget();
	}
	
	public Composite getEntityPanel() {
		return (Composite)this.viewPanel.getWidget();
	}
	
	public void clearView() {
		// Clear the entity search in combo fields
		Combo comboSearch = (Combo)this.gui.getWidget(InterfaceExplica.EXPLICA_ENTITY_SEARCH_COMBO_NAME);
		comboSearch.removeAll();
		
		// Clear the entity table registries
		Tree entityTree = this.getEntityTreeWidget();
		entityTree.clearAll(true);
		entityTree.removeAll();
		
		// Clear the comboSearch items list
		this.comboSearchItems.clear();
	}
	
	public void verifyEntityLauncher() {
		if (this.entityLauncher == null)
			try {
				throw new ExplicaException(
						ClientContext
								.getInstance()
								.getMsgCatalog()
								.newResultMessage(
										InterfaceErrors.ERR_NULL_ENTITY_LAUNCHER_ON_VIEW));
			} catch (ExplicaException e) {

				e.printStackTrace();
				System.exit(-1);
			}
	}
	
	public void updateView() {
		this.verifyEntityLauncher();
		this.fillEntityTable(this.entityLauncher.formatRegistries(
				this.entityLauncher.getLRegistries()));

	}
	
	private void unlinkGui() {
		if (this.gui != null && this.gui.getParentGui() != null) {
			this.gui.getParentGui().removeChild(this.gui);
			this.gui.setParentWidgetName(null);
			this.gui.setParentWindow(null);
		}
	}
	
	private void linkGui(Gui parentGui, SwtWidget parentWidget) {
		this.logger.debug("Linking View Panel: " + this.viewPanel);
		if (this.gui != null && parentGui != null && parentWidget != null) {
			this.gui.setParentGui(parentGui);
			parentGui.addChild(this.gui);
			this.gui.setParentWidgetName(parentWidget.getWidgetName());
			this.gui.setParentWindow(parentGui.getParentWindow());
			this.logger.debug("ROOT_WIDGET: " + this.gui.getRootWidget().getWidgetName());
			this.logger.debug("BEFORE_SETTING_PARENT: " + this.gui.getRootWidget().getParent());
			this.viewPanel.addChild(this.gui.getRootWidget());
			parentWidget.addChild(this.viewPanel);
			this.logger.debug("AFTER_SETTING_PARENT: " + this.viewPanel.getWidgetName() + "[" + this.viewPanel.getParent().getWidgetName() + "]");
			this.logger.debug("AFTER_SETTING_PARENT: " + this.gui.getRootWidget().getWidgetName() + "[" + this.gui.getRootWidget().getParent().getWidgetName() + "]");
			
			StringBuffer buf = new StringBuffer();
			for (SwtWidget child: parentWidget.getChildren()) {
				this.logger.debug(child);
				buf.append(child.getWidgetName());
				buf.append("\n");
			}
			this.logger.debug("PARENT_CHILDREN: " + parentWidget + " --> " + buf.toString());
		}
	}
	
	public void on_entity_hidden(Event e) {
		System.out.println("Entity hidden" + this.entityData.getName());
		this.logger.debug("Entity hidden: " + this.entityData.getName());
	}
	
	public void addExplicaEventListener(ExplicaEventListener l){
		listeners.add(l);
		
	}
	
	public void addExplicaEventListenerAllViews(ExplicaEventListener l){
		if (entityLauncher instanceof CommonClient)
			((CommonClient)this.entityLauncher).addExplicaEventListener(l);
		
	}
	
	public void removeExplicaEventListener(ExplicaEventListener l){
		listeners.remove(l);
	}
	
	
	public void notifyEvent(int type){
		this.logger.debug("Disparando evento para "+listeners.size()+ " listeners");
		ExplicaEvent event=new ExplicaEvent(this, type);
		for (ExplicaEventListener l:listeners)
			l.explicaViewModified(event);
		
	}

	/**
	 * Calculates the number of visible fields of the entity.
	 * @return int, visible fields number; 1 in case no visible fields
	 * have been defined.
	 */
	protected int getVisibleFieldsCount() {
		int numFields = 0;
		if (this.entityData.getLFields() != null && this.entityData.getLFields().size() > 0) {
			for (FieldOT field : this.entityData.getLFields()) {
				if (field.isVisible())
					numFields++;
			}
		}
		
		return numFields==0?1:numFields;
	}
	
	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: ExplicaEntityView.java,v 1.19 2009-10-27 10:09:06 mario Exp $";
	}
}